#include "../proto/proto.h"
#include "../server/media_lib.h"
#include <errno.h>
#include <signal.h>
#include <sys/wait.h>

#define BUFFSIZE 1024

static void sig_hanler(int s){}

int main (void)
{
	pid_t pid;
	int pfd[2] = {};
	int udp_socket;
	struct sockaddr_in myaddr;
	struct ip_mreqn imr;
	union chn_msg_st *rcv_msg;
	struct chn_list_st *rcv_list;
	struct chn_list_entry *entry;
	struct chn_data_st *rcv_data;
	int choose;
	int len;

	signal (SIGINT, sig_hanler);

	//创建管道, 子进程读管道, 父进程从组播中接受数据并写管道
	if (-1 == pipe (pfd))
	{
		perror ("pipe()");
		exit (1);
	}
	pid = fork();
	if (-1 == pid) {
		perror ("fork()");
		goto ERROR;
	}
	if (0 == pid) {
		//读管道
		close (pfd[1]);
		dup2 (pfd[0], 0);
		pause ();//等待信号的到来

#if 0
		char buf[BUFFSIZE] = {};
		int cnt = 0;
		while (1) {
			cnt = read (0, buf, BUFFSIZE);
			if (-1 == cnt) {
				perror ("read()");
				exit (1);
			} else if (0 == cnt) {
				exit (0);
			} 
			write (1, buf, cnt);
		}
#endif
	
		execl ("/usr/bin/mplayer", "mplayer", "-", NULL);
		perror ("execl()");
		exit (1);
	}
	close (pfd[0]);

	//从组播中接受数据并写管道
	//初始化套接字
	udp_socket = socket (AF_INET, SOCK_DGRAM, 0);
	if (-1 == udp_socket) {
		perror ("udp_socket");
		exit (1);
	}
	//被动端要bind组播地址
	myaddr.sin_family = AF_INET;
	myaddr.sin_port = htons (atoi(RCV_PORT));
	inet_aton("0.0.0.0", &myaddr.sin_addr);

	if (-1 == bind(udp_socket, (struct sockaddr *)&myaddr, sizeof(myaddr))) {
		perror ("bind()");
		close (udp_socket);
		goto ERROR;
	}

	//加入多播组
	inet_aton (GROUP_IP, &imr.imr_multiaddr);
	inet_aton ("0.0.0.0", &imr.imr_address);
	imr.imr_ifindex = if_nametoindex("ens33");
	if (-1 == setsockopt (udp_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, &imr, sizeof (imr)))
	{
		perror ("setsockopt()");
		goto ERROR;
	}

	//从多播组中接受数据
	rcv_msg = malloc (MAX_SIZE);
	if(NULL == rcv_msg) {
		return -ENOMEM;
	}
	//接受并打印频道列表
	while (1) {
		len = recvfrom (udp_socket, rcv_msg, MAX_SIZE, 0, NULL, NULL);
		if (-1 == len) {
			if (errno == EINTR){
				continue;
			}
			perror ("recvfrom()");
			goto ERROR;
		}
		if (0 == len) {
			break;
		}
		if (rcv_msg->chnid == CHN_LIST_ID) {
			break;
		}
	}
	//如果接受到频道列表, 将频道列表打印输出
	rcv_list = (void *)rcv_msg;
	for (entry = (void *)((char *)rcv_list + sizeof(rcv_list->chnid)); (char *)entry - (char *)rcv_list < len; \
			entry = (void *)((char *)entry + entry->len)){
		printf ("%d %s\n", entry->chnid, entry->descr);
		sleep (1);
	}

	//选择一个频道
	printf ("请选择一个频道(1~200):");
	scanf ("%d", &choose);

	kill (pid, SIGINT);

	//接受频道的数据
	rcv_data = (void *)rcv_msg;
	while (1) {
		memset (rcv_data, '\0', MAX_SIZE);
		len = recvfrom (udp_socket, rcv_data, MAX_SIZE, 0, NULL, NULL);
		if (-1 == len) {
			if (errno == EINTR) {
				continue;
			}
			perror ("recvfrom()");
			goto ERROR;
		}
		if(0 == len){
			break;
		}
		if (rcv_data->chnid != choose) {
			continue;
		}
		write (pfd[1], rcv_data->msg, len - sizeof (rcv_data->chnid));
	}
	printf ("您选择的频道关闭了, byebye!\n");

	free (rcv_msg);
	rcv_msg = NULL;
	close (udp_socket);
	close (pfd[1]);
	wait (NULL);
	exit (0);
ERROR:
	close (pfd[0]);
	close (pfd[1]);
}


